<template>
    <div style="position: fixed;width: 100%;height: 100%;left: 0;top: 0;" :style="{
        // zoom: rpx(1, true)
    }">
        <div v-if="show && ism()" style="width: 100%;height: 100%;position: relative;">
            <div style="width: 100%;height: 32px;padding: 0 16px;">
                <div style="width: 100%;height: 100%;display: flex;align-items: flex-end;">
                    <span @click="model.handleChange()" style="font-weight: bold;margin-right: 3px;">{{
                        model.form.model_id }}<span v-if="model.form.type === 'auto'"
                            style="font-size: 14px;color: gray;font-family: sans-serif;margin-left: 6px;"> {{ model.currentModelId
                            }}</span></span><span>></span>

                    <svg @click="() => {
                        // settings()
                        adminSettings()
                    }" style="position: absolute;right: 10px;top: 10px;" xmlns="http://www.w3.org/2000/svg"
                        height="20px" viewBox="0 -960 960 960" width="20px" fill="#1f1f1f">
                        <path
                            d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" />
                    </svg>
                </div>
            </div>
            <div style="width: 100%;height: calc(100% - 70px - 32px);position: relative;">
                <img style="width: 100%;height: 100%;object-fit: contain;position: absolute;;left: 0;top: 0;"
                    src="../assets/image_chat_bg.png" alt="">
                <div class="no-scroll-bar" id="chatMsg"
                    style="width: 100%;height: 100%;position: absolute;left: 0;top: 0;padding-top: 16px;">
                    <messageItem @finished="() => {
                        // item.animation = false
                    }" v-for="(item, index) in chatList.list" :item="item"></messageItem>
                    <messageItem
                        v-if="chatBox.sending && chatList.list.length && chatList.list[chatList.list.length - 1].type === 1"
                        :loading="true"></messageItem>
                </div>
            </div>
            <div style="width: 100%;height: 70px;position: relative;padding: 12px;">
                <div
                    style="width: 100%;height: 100%;border-radius: 8px;border: 0.5px solid lightgray;position: relative;overflow: hidden;">
                    <input @keypress="(e) => {
                        if (e.code == 'Enter') {
                            chatBox.handleSend()
                        }
                    }" placeholder="您可以向我提问"
                        style="position: absolute;left: 0;top: 0;height: 100%;width: calc(100% - 70px + 24px);padding-left: 8px;"
                        v-model="chatBox.input" type="text">
                    <div
                        style="display: inline-block;width: calc(70px - 24px);height: calc(70px - 24px);position: absolute;top: 0;right: 0;">
                        <div
                            style="width: 100%;height: 100%;display: flex;align-items: center;justify-content: center;">
                            <img v-if="chatBox.sending === false && !chatBox.input" style="width: 28px;height: 28px;"
                                src="../assets/icon_send_n.png" alt="">
                            <img @click="chatBox.handleSend()" v-if="chatBox.sending === false && chatBox.input"
                                style="width: 28px;height: 28px;" src="../assets/icon_send_f.png" alt="">
                            <img @click="tool.store.setItem('stop')" v-if="chatBox.sending"
                                style="width: 28px;height: 28px;" src="../assets/icon_send_s.png" alt="">
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div v-if="show && !ism()" style="width: 100%;height: 100%;position: fixed;left: 0;top: 0;display: flex;">
            <div
                style="width: 90px;height: 100%;display: inline-block;position: absolute;left: 0;top: 0;background-color: rgb(242,242,242);">
                <div
                    style="width: 100%;height: 70px;display: flex;align-items: center;justify-content: center;font-size: 18px;color: gray;font-weight: bold;">
                    RuruAI
                </div>
                <div style="width: 100%;height: 80px;padding: 8px;">
                    <div
                        style="width: 100%;height: 100%;border-radius: 8px;display: flex;align-items: center;justify-content: center;flex-direction: column;gap: 4px;background-color: rgba(0,0,0,0.1);">
                        <img style="width: 25px;height: 25px;" :src="ruruIcon" alt="">
                        <span style="font-size: 12px;">聊天</span>
                    </div>
                </div>
                <div
                    style="width: 100%;height: 80px;display: flex;align-items: center;justify-content: center;position: absolute;left: 0;bottom: 0;">
                    <svg @click="() => {
                        // settings()
                        adminSettings()
                    }" xmlns="http://www.w3.org/2000/svg" height="25px" viewBox="0 -960 960 960" width="25px"
                        fill="#1f1f1f">
                        <path
                            d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" />
                    </svg>
                </div>
            </div>
            <div
                style="width: calc(100% - 90px);height: 100%;position: absolute;right: 0;top: 0;display: flex;flex-direction: column;">
                <div style="width: 100%;height: 52px;padding: 0 16px;padding-bottom: 4px;min-height: 52px;">
                    <div style="width: 100%;height: 100%;display: flex;align-items: flex-end;font-size: 18px;">
                        <span @click="model.handleChange()" style="font-weight: bold;margin-right: 3px;">{{
                            model.form.model_id }}<span v-if="model.form.type === 'auto'"
                                style="font-size: 18px;color: gray;margin-left: 6px;"> {{ model.currentModelId
                                }}</span></span><span>></span>


                    </div>
                </div>
                <div id="chatMsgPC" style="width: 100%;height: 100%;overflow-y: auto;">
                    <div
                        style="width: 100%;max-width: 800px;height: auto;margin: 0 auto;display: flex;flex-direction: column;gap: 16px;padding-top: 32px;">
                        <div style="zoom: 1.2;width: 100%;display: flex;flex-direction: column;gap: 8px;">
                            <messageItem style="zoom:1.2;" @finished="() => {
                                // item.animation = false
                            }" v-for="(item, index) in chatList.list" :item="item"></messageItem>
                            <messageItem style="zoom:1.2;"
                                v-if="chatBox.sending && chatList.list.length && chatList.list[chatList.list.length - 1].type === 1"
                                :loading="true"></messageItem>
                        </div>
                        <div style="width: 100%;height: 160px;">

                        </div>
                    </div>

                    <div class="no-scroll-bar" v-if="chatBox.files.length"
                        style="width: calc(100% - 36px);height: 36px;position: absolute;bottom: 128px;left: 50%;transform: translateX(-50%);max-width: 764px;overflow-x: auto;">
                        <div
                            style="width: 100%;height: 100%;display: flex;align-items: center;justify-content: flex-start;gap: 8px;">
                            <div v-for="(item, index) in chatBox.files" :key="item.name" :title="item.name"
                                style="width: max-content;height: 100%;display: flex;border-radius: 16px;border: 1px solid rgb(230,230,230);font-size: 14px;line-height: 100%;align-items: center;justify-content: flex-start;max-width: 30%;word-break: keep-all;white-space: nowrap;text-overflow: ellipsis;padding: 0 8px;position: relative;">
                                <span style="width: 100%;text-overflow: ellipsis;padding-right: 18px;">{{ item.name
                                    }}</span>
                                <div
                                    style="display: inline-block;position: absolute;right: 4px;top: 0;width: 24px;height: 34px;">
                                    <div
                                        style="width: 100%;height: 100%;display: flex;align-items: center;justify-content: center;">
                                        <svg @click="() => {
                                            chatBox.files = chatBox.files.filter((_, i) => i !== index)
                                        }" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960"
                                            width="16px" fill="#1f1f1f">
                                            <path
                                                d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z" />
                                        </svg>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div
                        style="height: 100px;border: 1px solid rgb(230,230,230);border-radius: 16px;box-shadow: 0 4px 10px rgba(0,0,0,0.1);width: calc(100% - 36px);max-width: 764px;margin: 0 auto;position: absolute;left: 50%;bottom: 20px;transform: translateX(-50%);padding: 12px 16px;background-color: #fff;">
                        <input v-model="chatBox.input" @keypress="(e) => {
                            if (e.code == 'Enter') {
                                chatBox.handleSend()
                            }
                        }" placeholder="您可以向我提问" style="width: 100%;border: 0;font-size: 18px;" type="text">
                        <div style="width: auto;height: 36px;display: flex;position: absolute;left: 16px;bottom: 12px;align-items: center;justify-content: flex-start;"
                            class="no-scroll-bar">

                            <div @click="async () => {
                                if (chatBox.files.length >= 5) {
                                    tool.controls.toast.show({
                                        content: '最多只能上传5个文件',
                                        icon: 'error'
                                    })
                                    return
                                }
                                let re = await tool.selectFiles(5 - chatBox.files.length)
                                chatBox.files = [...chatBox.files, ...re]
                            }"
                                style="display: inline-block;border-radius: 14px;width: 104px;height: 28px;border: 1px solid rgb(230,230,230);cursor: pointer;">
                                <div
                                    style="width: 100%;height: 100%;display: flex;align-items: center;justify-content: center;gap: 4px;">
                                    <svg xmlns="http://www.w3.org/2000/svg" height="18px" viewBox="0 -960 960 960"
                                        width="18px" fill="#1f1f1f">
                                        <path
                                            d="M440-200h80v-167l64 64 56-57-160-160-160 160 57 56 63-63v167ZM240-80q-33 0-56.5-23.5T160-160v-640q0-33 23.5-56.5T240-880h320l240 240v480q0 33-23.5 56.5T720-80H240Zm280-520v-200H240v640h480v-440H520ZM240-800v200-200 640-640Z" />
                                    </svg>
                                    <span style="font-size: 14px;">上传文件</span>
                                </div>
                            </div>

                        </div>
                        <div class="no-scroll-bar"
                            style="width: 36px;height: 36px;display: flex;align-items: center;justify-content: center;position: absolute;bottom: 12px;right: 16px;scale: 1.2;overflow: hidden;overflow-y: hidden;">
                            <img v-if="chatBox.sending === false && !chatBox.input" style="width: 28px;height: 28px;"
                                src="../assets/icon_send_n.png" alt="">
                            <img @click="chatBox.handleSend()" v-if="chatBox.sending === false && chatBox.input"
                                style="width: 28px;height: 28px;" src="../assets/icon_send_f.png" alt="">
                            <img @click="tool.store.setItem('stop')" v-if="chatBox.sending"
                                style="width: 28px;height: 28px;" src="../assets/icon_send_s.png" alt="">
                        </div>
                    </div>

                </div>
            </div>
        </div>
    </div>
</template>

<script setup>
import { ref, reactive, defineProps, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
import tool from '../tool';
import messageItem from '../components/messageItem.vue';
import ruruIcon from '../assets/icon_ruru_head.png'

const show = ref(false)

const mode = ref('Demo')
watch(() => mode, (to, from) => {
    tool.store.setItem('testMode', mode.value === '测试' ? true : undefined)
}, { deep: true })

const chatList = reactive({
    list: [],
    push: {
        async user(content) {
            chatList.list.push({
                content,
                type: 1,
                username: '您',
                animation: false
            })
            await nextTick()
            tool.scrollToBottom('chatMsg')
            tool.scrollToBottom('chatMsgPC')
        },
        async ruru(content, animation = true, verbose) {
            chatList.list.push({
                content,
                type: 0,
                username: '圆如',
                animation,
                verbose
            })
            await nextTick()
            tool.scrollToBottom('chatMsg')
            tool.scrollToBottom('chatMsgPC')
        },
        async info(content) {
            chatList.list.push({
                content,
                type: 2
            })
            await nextTick()
            tool.scrollToBottom('chatMsg')
            tool.scrollToBottom('chatMsgPC')
        }
    },
    async appendToBottom(string) {
        if (chatList.list.length === 0) return
        chatList.list[chatList.list.length - 1].content += string
        await nextTick()
        tool.scrollToBottom('chatMsg')
        tool.scrollToBottom('chatMsgPC')
    },
    setBottomVerbose(verbose) {
        chatList.list[chatList.list.length - 1].verbose = verbose
    }
})

const chatBox = reactive({
    input: '',
    files: [],
    searchOnline: false,
    sending: false,
    sendTokenIds: false,
    sendAtZeroSecond: false,
    appendChar: {
        first: true,
        working: false,
        list: [],
        add(string) {
            if (!string) return
            this.list = [...this.list, ...string.split('')]
            this.run()
        },
        async run() {
            if (this.working) return
            if (this.list.length === 0) return
            this.working = true
            while (1) {
                if (this.list.length === 0) {
                    this.working = false
                    return
                }
                if (this.first) {
                    this.first = false
                    chatList.push.ruru('', true)
                }
                if (this.list[0] === '\uFFFD') {
                    this.list.shift()
                    console.log(chatList.list[chatList.list.length-1].content)
                    tool.store.setItem('stop')
                } else {
                    chatList.appendToBottom(this.list.shift())
                }

                await tool.wait(0.0005)
            }
        },
        end() {
            console.log(chatList.list)
            this.first = true
        }
    },
    handleChangeSendingStatus(sending) {
        tool.store.setItem('sending', sending)
    },
    async handleSend() {
        if (this.sending) return
        if (!this.input) return
        if (this.sendTokenIds && !tool.isValidHexTokens(this.input)) {
            tool.controls.toast.show({
                content: '输入的TokenIds格式不正确',
                icon: 'error'
            })
            return
        }
        let input = this.input
        chatList.push.user(this.input)
        this.input = ''

        let files = this.files
        this.files = []
        this.handleChangeSendingStatus(true)
        if (this.sendAtZeroSecond) {
            await new Promise((resolve, reject) => {
                let it = setInterval(() => {
                    let time = new Date()
                    tool.controls.toast.show({
                        content: `${60 - time.getSeconds()}秒后发送`,
                    })
                    if (time.getSeconds() === 0) {
                        clearInterval(it)
                        tool.controls.toast.hide()
                        resolve()
                    }
                }, 10);
            })
        }
        let filenames = []
        await tool.flow(async () => {
            for (let i = 0; i < files.length; i++) {
                let re = await tool.uploadFile(files[i])
                try {
                    re = JSON.parse(re)
                } catch (error) {

                }
                if (re.status) {
                    filenames.push(re.data)
                }
            }
        }, err => 1)

        tool.flow(async () => {
            let startTime = new Date()
            let re_time = await tool.requestData('/app/serverTime', {}, 'get', false)
            if (!re_time.status) {
                throw re_time.content
            }
            let endTime = new Date()
            let allowSend = true
            let remainString = ''
            let re = await tool.requestStream('/app/chat', {
                "model_id": model.form.model_id,
                "session_id": welcome.session_id,
                "prompt": input,
                "UIStartTime": parseInt((new Date(re_time.data)).getTime() + (endTime.getTime() - startTime.getTime()) / 2),
                "mode": mode.value,
                sendTokenIds: this.sendTokenIds,
                files:filenames,
                searchOnline: this.searchOnline
            }, 'post', false, (e) => {
                if (allowSend === false) return
                if (!this.sending) {
                    tool.store.setItem('stop')
                    allowSend = false
                    return
                }
                try {
                    e = tool.splitJsonObjects(remainString + e)
                    remainString = e.last
                    e = e.data
                } catch (error) {

                }
                e.forEach(item => {
                    if (item.end) {
                        setTimeout(() => {
                            this.appendChar.add('\uFFFD')
                            chatList.setBottomVerbose(item.verbose)
                        }, 500);

                        return
                    }
                    this.appendChar.add(item.response)
                })
            })
            if (re.status) {
                // if (this.sending)
                //     chatList.push.ruru(re.data.response, true, re.data.verbose)
            } else {
                throw re.content
            }
            return
            re = await tool.requestData('/app/chat', {
                "model_id": model.form.model_id,
                "session_id": welcome.session_id,
                "prompt": input,
                "UIStartTime": parseInt((new Date(re_time.data)).getTime() + (endTime.getTime() - startTime.getTime()) / 2),
                "mode": mode.value
            }, 'post', false)
            if (re.status) {
                if (this.sending)
                    chatList.push.ruru(re.data.response, true, re.data.verbose)
            } else {
                throw re.content
            }
        }, error => {
            if (error) {
                this.handleChangeSendingStatus(false)
                chatList.push.info(`${error}`)
            }

        })
    },
    init() {
        tool.store.onChange('sending', (e) => {
            this.sending = e
        })
    }
})
chatBox.init()
tool.store.onChange('stop', () => {
    chatBox.appendChar.end()
})

const status = ref(0)
tool.store.onChangeAndNotify('windowStatus', (e) => {
    status.value = e
})

const ism = tool.getIsMobileFunction()

const model = reactive({
    list: [],
    form: {
        model_id: '自动',
        type: 'auto'
    },
    currentModelId: '',
    async get() {
        let re = await tool.requestData('/app/switch_model', this.form)
        if (re.status) {
            this.form.model_id = re.data
        } else {
            throw re.content
        }
    },
    handleChange() {
        let select_model_control = tool.controls.actionSheet({
            list: (() => {
                let re = []
                for (let i = 0; i < model.list.length; i++) {
                    re.push({
                        name: `${model.list[i].model_id}${model.list[i].type === 'auto' ? '' : ` (${model.list[i].hostName}, ${model.list[i].type === 'circuit' ? '硬件' : '软件'})`}`,
                        callBack() {
                            localStorage.setItem('selectedModel', JSON.stringify({
                                model_id: model.list[i].model_id,
                                type: model.list[i].type
                            }))
                            select_model_control.close()
                            location.reload()
                        }
                    })
                }
                return re
            })(),
            tip: '选择模型'
        })
    }
})

const welcome = reactive({
    session_id: undefined,
    async get() {
        let re = await tool.requestData('/app/get-welcome-message', (() => {
            let selectedModel = localStorage.getItem('selectedModel')
            localStorage.removeItem('selectedModel')
            if (selectedModel === null) {

            } else {
                selectedModel = JSON.parse(selectedModel)
                model.form.model_id = selectedModel.model_id
                model.form.type = selectedModel.type
            }
            return {
                ...model.form
            }
        })(), 'get')
        if (re.status) {
            return re.data
        } else {
            throw re.content
        }
    }
})

const adminSettings = () => {
    const show = () => {
        tool.settings.show('设置', (refreshPage_settings) => {
            return () => {
                return [
                    {
                        title: 'Host',
                        list: [
                            {
                                title: '查看在线的Host',
                                async callBack() {
                                    // if(await new Promise((resolve, reject) => {
                                    //     tool.controls.input
                                    // }))return
                                    let hostList = []
                                    const getHostList = async () => {
                                        let re = await tool.requestData('/app/config/hostList', {}, 'get')
                                        if (re.status) {
                                            return re.data
                                        } else {
                                            throw re.content
                                        }
                                    }
                                    await tool.flow(async () => {
                                        tool.settings.show('在线的Host', async (refreshPage_onlineHosts) => {
                                            const handleShowHostConfigMenu = async (hostName) => {
                                                tool.settings.show(`${hostName}`, () => {
                                                    return () => {
                                                        return [
                                                            {
                                                                list: [
                                                                    {
                                                                        title: '重启后端程序',
                                                                        async callBack() {
                                                                            tool.controls.modal({
                                                                                title: '提示',
                                                                                content: '此HOST的会话信息会全部丢失，是否继续？',
                                                                                showCancel: true,
                                                                                async okCallBack() {
                                                                                    let re = await tool.requestData('/app/config/hostInfo_edit', {
                                                                                        hostName,
                                                                                        op: 'restart',
                                                                                        data: {}
                                                                                    })
                                                                                    if (re.status) {
                                                                                        tool.settings.close.top()
                                                                                        tool.controls.closeTop()
                                                                                        tool.controls.toast.show({
                                                                                            content: '指令已发送，大约3秒后重启成功',
                                                                                            icon: 'info',
                                                                                            time: 1500
                                                                                        })
                                                                                        setTimeout(async () => {
                                                                                            try {
                                                                                                hostList = await getHostList()
                                                                                                refreshPage_onlineHosts()
                                                                                            } catch (error) {

                                                                                            }
                                                                                        }, 1000);
                                                                                        setTimeout(async () => {
                                                                                            try {
                                                                                                hostList = await getHostList()
                                                                                                refreshPage_onlineHosts()
                                                                                            } catch (error) {

                                                                                            }
                                                                                        }, 4000);
                                                                                    } else {
                                                                                        tool.controls.toast.show({
                                                                                            content: `${re.content}`,
                                                                                            icon: 'error',
                                                                                            time: 1500
                                                                                        })
                                                                                    }
                                                                                }
                                                                            })
                                                                        }
                                                                    },
                                                                    {
                                                                        title: '编辑配置',
                                                                        async callBack() {
                                                                            await tool.flow(async () => {
                                                                                let re = await tool.requestData('/app/config/get', {
                                                                                    hostName
                                                                                }, 'get')
                                                                                if (re.status) {
                                                                                    let hostName = re.data.hostName
                                                                                    let hostConfig = re.data
                                                                                    let edited = ref(false)
                                                                                    tool.settings.show(`编辑${hostName}的配置`, async (refreshPage_editConfig) => {
                                                                                        watch(() => edited, () => {
                                                                                            refreshPage_editConfig()
                                                                                        }, { deep: true })
                                                                                        const setEdited = () => edited.value = true
                                                                                        return () => {
                                                                                            return [
                                                                                                ...(() => {
                                                                                                    if (edited.value) {
                                                                                                        return [
                                                                                                            {
                                                                                                                title: '您有未保存的修改，请点击右上角保存后再关闭',
                                                                                                            }
                                                                                                        ]
                                                                                                    } else {
                                                                                                        return []
                                                                                                    }
                                                                                                })(),
                                                                                                {
                                                                                                    title: '选项',
                                                                                                    list: [
                                                                                                        {
                                                                                                            title: "名称",
                                                                                                            right: {
                                                                                                                type: 'text',
                                                                                                                value: `${hostConfig.hostName}${hostConfig.hostName === hostName ? '' : ` (修改前:${hostName})`}`
                                                                                                            },
                                                                                                            callBack() {
                                                                                                                let input = tool.controls.input.singleText({
                                                                                                                    title: '名称',
                                                                                                                    value: hostConfig.hostName,
                                                                                                                    async okCallBack(e) {
                                                                                                                        setEdited()
                                                                                                                        hostConfig.hostName = e
                                                                                                                        refreshPage_editConfig()
                                                                                                                        input.close()
                                                                                                                    },
                                                                                                                    checkCallBack(e) {
                                                                                                                        if (!e) throw '名称不能为空'
                                                                                                                    }
                                                                                                                })
                                                                                                            }
                                                                                                        },
                                                                                                        {
                                                                                                            title: '会话超时时间',
                                                                                                            right: {
                                                                                                                type: 'text',
                                                                                                                value: `${hostConfig.chatTimeout} 毫秒`
                                                                                                            },
                                                                                                            async callBack() {
                                                                                                                let input = tool.controls.input.singleText({
                                                                                                                    title: '会话超时时间',
                                                                                                                    value: hostConfig.chatTimeout,
                                                                                                                    async okCallBack(e) {
                                                                                                                        setEdited()
                                                                                                                        hostConfig.chatTimeout = e
                                                                                                                        refreshPage_editConfig()
                                                                                                                        input.close()
                                                                                                                    },
                                                                                                                    checkCallBack(e) {
                                                                                                                        if (!e) throw '输入会话超时时间'
                                                                                                                        e = parseInt(e)
                                                                                                                        if (isNaN(e) || e < 0) throw '会话超时时间应为自然数'
                                                                                                                    }
                                                                                                                })
                                                                                                            }
                                                                                                        }
                                                                                                    ]
                                                                                                },
                                                                                                {
                                                                                                    title: '设备',
                                                                                                    list: (() => {
                                                                                                        let re = []
                                                                                                        for (let i = 0; i < hostConfig.devices.length; i++) {
                                                                                                            re.push({
                                                                                                                title: hostConfig.devices[i].name,
                                                                                                                callBack: async () => {
                                                                                                                    await new Promise((resolve, reject) => {
                                                                                                                        let as = tool.controls.actionSheet({
                                                                                                                            tip: hostConfig.devices[i].name,
                                                                                                                            list: [
                                                                                                                                {
                                                                                                                                    name: '删除',
                                                                                                                                    callBack() {
                                                                                                                                        let dm = tool.controls.modal({
                                                                                                                                            title: '提示',
                                                                                                                                            content: `是否删除设备 ${hostConfig.devices[i].name}？`,
                                                                                                                                            showCancel: true,
                                                                                                                                            okCallBack: () => {
                                                                                                                                                hostConfig.devices.splice(i, 1)
                                                                                                                                                setEdited()
                                                                                                                                                refreshPage_editConfig()
                                                                                                                                                as.close()
                                                                                                                                                dm.close()
                                                                                                                                            }
                                                                                                                                        })
                                                                                                                                    }
                                                                                                                                },
                                                                                                                                {
                                                                                                                                    name: '编辑',
                                                                                                                                    callBack: () => {
                                                                                                                                        resolve()
                                                                                                                                        as.close()
                                                                                                                                    }
                                                                                                                                },
                                                                                                                                {
                                                                                                                                    name: '复制',
                                                                                                                                    callBack() {
                                                                                                                                        let input = tool.controls.input.singleText({
                                                                                                                                            title: '输入新设备的名称',
                                                                                                                                            checkCallBack(e) {
                                                                                                                                                for (let i = 0; i < hostConfig.devices.length; i++) {
                                                                                                                                                    if (hostConfig.devices[i].name === e) throw '设备名称已存在'
                                                                                                                                                }
                                                                                                                                            },
                                                                                                                                            okCallBack(e) {
                                                                                                                                                let newConfig = JSON.parse(JSON.stringify(hostConfig.devices[i]))
                                                                                                                                                newConfig.name = e
                                                                                                                                                hostConfig.devices.push(newConfig)
                                                                                                                                                setEdited()
                                                                                                                                                input.close()
                                                                                                                                                refreshPage_editConfig()
                                                                                                                                            }
                                                                                                                                        })
                                                                                                                                        as.close()
                                                                                                                                    }
                                                                                                                                }
                                                                                                                            ]
                                                                                                                        })
                                                                                                                    })
                                                                                                                    let deviceConfig = hostConfig.devices[i]
                                                                                                                    tool.settings.show(`编辑${hostConfig.devices[i].name}的配置`, async (refreshPage_editDeviceConfig) => {
                                                                                                                        return () => {
                                                                                                                            return [
                                                                                                                                {
                                                                                                                                    title: `所在host名称: ${hostName}`
                                                                                                                                },
                                                                                                                                {
                                                                                                                                    title: `选项`,
                                                                                                                                    list: [
                                                                                                                                        {
                                                                                                                                            title: '启用该设备',
                                                                                                                                            right: {
                                                                                                                                                type: 'switch',
                                                                                                                                                value: deviceConfig.enable
                                                                                                                                            },
                                                                                                                                            callBack(e) {
                                                                                                                                                deviceConfig.enable = e
                                                                                                                                                refreshPage_editDeviceConfig()
                                                                                                                                                setEdited()
                                                                                                                                            }
                                                                                                                                        },
                                                                                                                                        {
                                                                                                                                            title: '类型',
                                                                                                                                            right: {
                                                                                                                                                type: 'text',
                                                                                                                                                value: deviceConfig.type === 'circuit' ? '硬件' : '软件'
                                                                                                                                            },
                                                                                                                                            callBack() {
                                                                                                                                                let as = tool.controls.actionSheet({
                                                                                                                                                    tip: '选择设备类型',
                                                                                                                                                    list: [
                                                                                                                                                        {
                                                                                                                                                            name: '硬件',
                                                                                                                                                            callBack() {
                                                                                                                                                                setEdited()
                                                                                                                                                                deviceConfig.type = 'circuit'
                                                                                                                                                                refreshPage_editDeviceConfig()
                                                                                                                                                                as.close()
                                                                                                                                                            }
                                                                                                                                                        },
                                                                                                                                                        {
                                                                                                                                                            name: '软件',
                                                                                                                                                            callBack() {
                                                                                                                                                                if (hostConfig.ollamaInstalledModels.length === 0) {
                                                                                                                                                                    as.close()
                                                                                                                                                                    tool.controls.toast.show({
                                                                                                                                                                        content: '无可用的软件模型'
                                                                                                                                                                    })
                                                                                                                                                                    return
                                                                                                                                                                }
                                                                                                                                                                if (hostConfig.ollamaInstalledModels.indexOf(deviceConfig.ollama.model) === -1) {
                                                                                                                                                                    deviceConfig.ollama.model = hostConfig.ollamaInstalledModels[0]
                                                                                                                                                                }
                                                                                                                                                                setEdited()
                                                                                                                                                                deviceConfig.type = 'ollama'
                                                                                                                                                                refreshPage_editDeviceConfig()
                                                                                                                                                                as.close()
                                                                                                                                                            }
                                                                                                                                                        },
                                                                                                                                                    ]
                                                                                                                                                })
                                                                                                                                            }
                                                                                                                                        },
                                                                                                                                        ...(() => {
                                                                                                                                            if (deviceConfig.type === 'circuit') {
                                                                                                                                                return [
                                                                                                                                                    {
                                                                                                                                                        title: '硬件设备名称',
                                                                                                                                                        right: {
                                                                                                                                                            type: 'text',
                                                                                                                                                            value: deviceConfig.circuit.name
                                                                                                                                                        },
                                                                                                                                                        callBack() {
                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                value: deviceConfig.circuit.name,
                                                                                                                                                                title: '输入硬件设备名称',
                                                                                                                                                                checkCallBack(e) {
                                                                                                                                                                    if (!e) throw '硬件设备名称不能为空'
                                                                                                                                                                },
                                                                                                                                                                okCallBack(e) {
                                                                                                                                                                    setEdited()
                                                                                                                                                                    input.close()
                                                                                                                                                                    deviceConfig.circuit.name = e
                                                                                                                                                                    refreshPage_editDeviceConfig()
                                                                                                                                                                }
                                                                                                                                                            })
                                                                                                                                                        }
                                                                                                                                                    }
                                                                                                                                                ]
                                                                                                                                            } else {
                                                                                                                                                return [
                                                                                                                                                    {
                                                                                                                                                        title: '软件模型',
                                                                                                                                                        right: {
                                                                                                                                                            type: "text",
                                                                                                                                                            value: deviceConfig.ollama.model
                                                                                                                                                        },
                                                                                                                                                        callBack() {
                                                                                                                                                            let as = tool.controls.actionSheet({
                                                                                                                                                                tip: '选择软件模型',
                                                                                                                                                                list: (() => {
                                                                                                                                                                    let re = []
                                                                                                                                                                    hostConfig.ollamaInstalledModels.forEach(item => {
                                                                                                                                                                        re.push({
                                                                                                                                                                            name: item,
                                                                                                                                                                            callBack() {
                                                                                                                                                                                as.close()
                                                                                                                                                                                deviceConfig.ollama.model = item
                                                                                                                                                                                setEdited()
                                                                                                                                                                                refreshPage_editDeviceConfig()
                                                                                                                                                                            }
                                                                                                                                                                        })
                                                                                                                                                                    })
                                                                                                                                                                    return re
                                                                                                                                                                })()
                                                                                                                                                            })
                                                                                                                                                        }
                                                                                                                                                    }
                                                                                                                                                ]
                                                                                                                                            }
                                                                                                                                        })()
                                                                                                                                    ]
                                                                                                                                },
                                                                                                                                {
                                                                                                                                    title: '向设备发送数据',
                                                                                                                                    list: [
                                                                                                                                        {
                                                                                                                                            title: `启用 ${deviceConfig.DMAToDevice.enable ? '' : '(当前为虚拟回复)'}`,
                                                                                                                                            right: {
                                                                                                                                                type: 'switch',
                                                                                                                                                value: (() => {
                                                                                                                                                    if (deviceConfig.DMAToDevice.enable) {
                                                                                                                                                        return true
                                                                                                                                                    } else {
                                                                                                                                                        return false
                                                                                                                                                    }
                                                                                                                                                })()
                                                                                                                                            },
                                                                                                                                            callBack(e) {
                                                                                                                                                setEdited()
                                                                                                                                                deviceConfig.DMAToDevice.enable = e
                                                                                                                                                refreshPage_editDeviceConfig()
                                                                                                                                                as.close()
                                                                                                                                            }
                                                                                                                                        },
                                                                                                                                        ...(() => {
                                                                                                                                            if (deviceConfig.DMAToDevice.enable) {
                                                                                                                                                return [
                                                                                                                                                    ...(() => {
                                                                                                                                                        if (deviceConfig.type === 'circuit') {
                                                                                                                                                            return [
                                                                                                                                                                {
                                                                                                                                                                    title: 'Token存文件',
                                                                                                                                                                    right: {
                                                                                                                                                                        type: 'switch',
                                                                                                                                                                        value: (() => {
                                                                                                                                                                            if (deviceConfig.DMAToDevice.file) {
                                                                                                                                                                                return true
                                                                                                                                                                            } else {
                                                                                                                                                                                return false
                                                                                                                                                                            }
                                                                                                                                                                        })()
                                                                                                                                                                    },
                                                                                                                                                                    callBack(e) {
                                                                                                                                                                        setEdited()
                                                                                                                                                                        deviceConfig.DMAToDevice.file = e
                                                                                                                                                                        refreshPage_editDeviceConfig()
                                                                                                                                                                        as.close()
                                                                                                                                                                    }
                                                                                                                                                                }
                                                                                                                                                            ]
                                                                                                                                                        } else {
                                                                                                                                                            return []
                                                                                                                                                        }
                                                                                                                                                    })(),
                                                                                                                                                    {
                                                                                                                                                        title: 'Token数量',
                                                                                                                                                        right: {
                                                                                                                                                            type: 'text',
                                                                                                                                                            value: deviceConfig.DMAToDevice.tokenNum,
                                                                                                                                                        },
                                                                                                                                                        async callBack() {
                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                title: 'DMAToDevice Token数量',
                                                                                                                                                                value: deviceConfig.DMAToDevice.tokenNum,
                                                                                                                                                                async okCallBack(e) {
                                                                                                                                                                    deviceConfig.DMAToDevice.tokenNum = parseInt(e)
                                                                                                                                                                    deviceConfig.DMAToDevice.size = parseInt(e) * 2
                                                                                                                                                                    refreshPage_editDeviceConfig()
                                                                                                                                                                    input.close()
                                                                                                                                                                    setEdited()
                                                                                                                                                                },
                                                                                                                                                                checkCallBack(e) {
                                                                                                                                                                    e = parseInt(e)
                                                                                                                                                                    if (isNaN(e) || e < 0) throw '应为自然数'
                                                                                                                                                                    let sum = 0
                                                                                                                                                                    for (let i = 0; i < deviceConfig.DMAToDevice.channels.length; i++) {
                                                                                                                                                                        sum += deviceConfig.DMAToDevice.channels[i].size
                                                                                                                                                                    }
                                                                                                                                                                    if (e < sum) throw 'Token数量不能少于所有输入通道占用的Token数量的总和'
                                                                                                                                                                }
                                                                                                                                                            })
                                                                                                                                                        }
                                                                                                                                                    },
                                                                                                                                                    {
                                                                                                                                                        title: '起始标志',
                                                                                                                                                        right: {
                                                                                                                                                            type: 'text',
                                                                                                                                                            value: deviceConfig.DMAToDevice.marks.start
                                                                                                                                                        },
                                                                                                                                                        async callBack() {
                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                title: 'DMAToDevice 起始标志',
                                                                                                                                                                value: deviceConfig.DMAToDevice.marks.start,
                                                                                                                                                                async okCallBack(e) {
                                                                                                                                                                    deviceConfig.DMAToDevice.marks.start = e
                                                                                                                                                                    refreshPage_editDeviceConfig()
                                                                                                                                                                    input.close()
                                                                                                                                                                    setEdited()
                                                                                                                                                                },
                                                                                                                                                                checkCallBack(e = '') {
                                                                                                                                                                    if (e.match(/[0-9a-zA-Z]{4}/g) === null) throw '应为4位十六进制数'
                                                                                                                                                                    if (e === deviceConfig.DMAToDevice.marks.end) throw '起始标志和结束标志重复'
                                                                                                                                                                    if (e === deviceConfig.DMAToDevice.marks.blank) throw '起始标志和空白标志重复'
                                                                                                                                                                }
                                                                                                                                                            })
                                                                                                                                                        }
                                                                                                                                                    },
                                                                                                                                                    {
                                                                                                                                                        title: '终止标志',
                                                                                                                                                        right: {
                                                                                                                                                            type: 'text',
                                                                                                                                                            value: deviceConfig.DMAToDevice.marks.end
                                                                                                                                                        },
                                                                                                                                                        async callBack() {
                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                title: 'DMAToDevice 终止标志',
                                                                                                                                                                value: deviceConfig.DMAToDevice.marks.end,
                                                                                                                                                                async okCallBack(e) {
                                                                                                                                                                    deviceConfig.DMAToDevice.marks.end = e
                                                                                                                                                                    refreshPage_editDeviceConfig()
                                                                                                                                                                    input.close()
                                                                                                                                                                    setEdited()
                                                                                                                                                                },
                                                                                                                                                                checkCallBack(e = '') {
                                                                                                                                                                    if (e.match(/[0-9a-zA-Z]{4}/g) === null) throw '应为4位十六进制数'
                                                                                                                                                                    if (e === deviceConfig.DMAToDevice.marks.start) throw '终止标志和起始标志重复'
                                                                                                                                                                    if (e === deviceConfig.DMAToDevice.marks.blank) throw '终止标志和空白标志重复'
                                                                                                                                                                }
                                                                                                                                                            })
                                                                                                                                                        }
                                                                                                                                                    },
                                                                                                                                                    {
                                                                                                                                                        title: '空白标志',
                                                                                                                                                        right: {
                                                                                                                                                            type: 'text',
                                                                                                                                                            value: deviceConfig.DMAToDevice.marks.blank
                                                                                                                                                        },
                                                                                                                                                        async callBack() {
                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                title: 'DMAToDevice 空白标志',
                                                                                                                                                                value: deviceConfig.DMAToDevice.marks.blank,
                                                                                                                                                                async okCallBack(e) {
                                                                                                                                                                    deviceConfig.DMAToDevice.marks.blank = e
                                                                                                                                                                    refreshPage_editDeviceConfig()
                                                                                                                                                                    input.close()
                                                                                                                                                                    setEdited()
                                                                                                                                                                },
                                                                                                                                                                checkCallBack(e = '') {
                                                                                                                                                                    if (e.match(/[0-9a-zA-Z]{4}/g) === null) throw '应为4位十六进制数'
                                                                                                                                                                    if (e === deviceConfig.DMAToDevice.marks.start) throw '空白标志和起始标志重复'
                                                                                                                                                                    if (e === deviceConfig.DMAToDevice.marks.end) throw '空白标志和结束标志重复'
                                                                                                                                                                }
                                                                                                                                                            })
                                                                                                                                                        }
                                                                                                                                                    },
                                                                                                                                                ]
                                                                                                                                            } else {
                                                                                                                                                return []
                                                                                                                                            }
                                                                                                                                        })()
                                                                                                                                    ]
                                                                                                                                },
                                                                                                                                {
                                                                                                                                    title: '从设备读出数据',
                                                                                                                                    list: [
                                                                                                                                        {
                                                                                                                                            title: '启用',
                                                                                                                                            right: {
                                                                                                                                                type: 'switch',
                                                                                                                                                value: (() => {
                                                                                                                                                    if (deviceConfig.DMAFromDevice.enable) {
                                                                                                                                                        return true
                                                                                                                                                    } else {
                                                                                                                                                        return false
                                                                                                                                                    }
                                                                                                                                                })()
                                                                                                                                            },
                                                                                                                                            callBack(e) {
                                                                                                                                                setEdited()
                                                                                                                                                deviceConfig.DMAFromDevice.enable = e
                                                                                                                                                refreshPage_editDeviceConfig()
                                                                                                                                                as.close()
                                                                                                                                            }
                                                                                                                                        },
                                                                                                                                        ...(() => {
                                                                                                                                            if (deviceConfig.DMAFromDevice.enable) {
                                                                                                                                                return [
                                                                                                                                                    ...(() => {
                                                                                                                                                        if (deviceConfig.type === 'circuit') {
                                                                                                                                                            return [
                                                                                                                                                                {
                                                                                                                                                                    title: 'Token存文件',
                                                                                                                                                                    right: {
                                                                                                                                                                        type: 'switch',
                                                                                                                                                                        value: (() => {
                                                                                                                                                                            if (deviceConfig.DMAFromDevice.file) {
                                                                                                                                                                                return true
                                                                                                                                                                            } else {
                                                                                                                                                                                return false
                                                                                                                                                                            }
                                                                                                                                                                        })()
                                                                                                                                                                    },
                                                                                                                                                                    callBack(e) {
                                                                                                                                                                        setEdited()
                                                                                                                                                                        deviceConfig.DMAFromDevice.file = e
                                                                                                                                                                        refreshPage_editDeviceConfig()
                                                                                                                                                                        as.close()
                                                                                                                                                                    }
                                                                                                                                                                }
                                                                                                                                                            ]
                                                                                                                                                        } else {
                                                                                                                                                            return []
                                                                                                                                                        }
                                                                                                                                                    })(),
                                                                                                                                                    {
                                                                                                                                                        title: 'Token数量',
                                                                                                                                                        right: {
                                                                                                                                                            type: 'text',
                                                                                                                                                            value: deviceConfig.DMAFromDevice.tokenNum,
                                                                                                                                                        },
                                                                                                                                                        async callBack() {
                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                title: 'DMAFromDevice Token数量',
                                                                                                                                                                value: deviceConfig.DMAFromDevice.tokenNum,
                                                                                                                                                                async okCallBack(e) {
                                                                                                                                                                    deviceConfig.DMAFromDevice.tokenNum = parseInt(e)
                                                                                                                                                                    deviceConfig.DMAFromDevice.size = parseInt(e) * 2
                                                                                                                                                                    refreshPage_editDeviceConfig()
                                                                                                                                                                    input.close()
                                                                                                                                                                    setEdited()
                                                                                                                                                                },
                                                                                                                                                                checkCallBack(e) {
                                                                                                                                                                    e = parseInt(e)
                                                                                                                                                                    if (isNaN(e) || e < 0) throw '应为自然数'
                                                                                                                                                                    let sum = 0
                                                                                                                                                                    for (let i = 0; i < deviceConfig.DMAFromDevice.channels.length; i++) {
                                                                                                                                                                        sum += deviceConfig.DMAFromDevice.channels[i].size
                                                                                                                                                                    }
                                                                                                                                                                    if (e < sum) throw 'Token数量不能少于所有输入通道占用的Token数量的总和'
                                                                                                                                                                }
                                                                                                                                                            })
                                                                                                                                                        }
                                                                                                                                                    },
                                                                                                                                                    {
                                                                                                                                                        title: '起始标志',
                                                                                                                                                        right: {
                                                                                                                                                            type: 'text',
                                                                                                                                                            value: deviceConfig.DMAFromDevice.marks.start
                                                                                                                                                        },
                                                                                                                                                        async callBack() {
                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                title: 'DMAFromDevice 起始标志',
                                                                                                                                                                value: deviceConfig.DMAFromDevice.marks.start,
                                                                                                                                                                async okCallBack(e) {
                                                                                                                                                                    deviceConfig.DMAFromDevice.marks.start = e
                                                                                                                                                                    refreshPage_editDeviceConfig()
                                                                                                                                                                    input.close()
                                                                                                                                                                    setEdited()
                                                                                                                                                                },
                                                                                                                                                                checkCallBack(e = '') {
                                                                                                                                                                    if (e.match(/[0-9a-zA-Z]{4}/g) === null) throw '应为4位十六进制数'
                                                                                                                                                                    if (e === deviceConfig.DMAFromDevice.marks.end) throw '起始标志和结束标志重复'
                                                                                                                                                                    if (e === deviceConfig.DMAFromDevice.marks.blank) throw '起始标志和空白标志重复'
                                                                                                                                                                }
                                                                                                                                                            })
                                                                                                                                                        }
                                                                                                                                                    },
                                                                                                                                                    {
                                                                                                                                                        title: '终止标志',
                                                                                                                                                        right: {
                                                                                                                                                            type: 'text',
                                                                                                                                                            value: deviceConfig.DMAFromDevice.marks.end
                                                                                                                                                        },
                                                                                                                                                        async callBack() {
                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                title: 'DMAFromDevice 终止标志',
                                                                                                                                                                value: deviceConfig.DMAFromDevice.marks.end,
                                                                                                                                                                async okCallBack(e) {
                                                                                                                                                                    deviceConfig.DMAFromDevice.marks.end = e
                                                                                                                                                                    refreshPage_editDeviceConfig()
                                                                                                                                                                    input.close()
                                                                                                                                                                    setEdited()
                                                                                                                                                                },
                                                                                                                                                                checkCallBack(e = '') {
                                                                                                                                                                    if (e.match(/[0-9a-zA-Z]{4}/g) === null) throw '应为4位十六进制数'
                                                                                                                                                                    if (e === deviceConfig.DMAFromDevice.marks.start) throw '终止标志和起始标志重复'
                                                                                                                                                                    if (e === deviceConfig.DMAFromDevice.marks.blank) throw '终止标志和空白标志重复'
                                                                                                                                                                }
                                                                                                                                                            })
                                                                                                                                                        }
                                                                                                                                                    },
                                                                                                                                                    {
                                                                                                                                                        title: '空白标志',
                                                                                                                                                        right: {
                                                                                                                                                            type: 'text',
                                                                                                                                                            value: deviceConfig.DMAFromDevice.marks.blank
                                                                                                                                                        },
                                                                                                                                                        async callBack() {
                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                title: 'DMAFromDevice 空白标志',
                                                                                                                                                                value: deviceConfig.DMAFromDevice.marks.blank,
                                                                                                                                                                async okCallBack(e) {
                                                                                                                                                                    deviceConfig.DMAFromDevice.marks.blank = e
                                                                                                                                                                    refreshPage_editDeviceConfig()
                                                                                                                                                                    input.close()
                                                                                                                                                                    setEdited()
                                                                                                                                                                },
                                                                                                                                                                checkCallBack(e = '') {
                                                                                                                                                                    if (e.match(/[0-9a-zA-Z]{4}/g) === null) throw '应为4位十六进制数'
                                                                                                                                                                    if (e === deviceConfig.DMAFromDevice.marks.start) throw '空白标志和起始标志重复'
                                                                                                                                                                    if (e === deviceConfig.DMAFromDevice.marks.end) throw '空白标志和结束标志重复'
                                                                                                                                                                }
                                                                                                                                                            })
                                                                                                                                                        }
                                                                                                                                                    },
                                                                                                                                                    {
                                                                                                                                                        title: '对每个Token进行异或',
                                                                                                                                                        right: {
                                                                                                                                                            type: 'switch',
                                                                                                                                                            value: deviceConfig.DMAFromDevice.XOR
                                                                                                                                                        },
                                                                                                                                                        async callBack(e) {
                                                                                                                                                            deviceConfig.DMAFromDevice.XOR = e
                                                                                                                                                            refreshPage_editDeviceConfig()
                                                                                                                                                            setEdited()
                                                                                                                                                        }
                                                                                                                                                    },
                                                                                                                                                    ...(() => {
                                                                                                                                                        if (deviceConfig.DMAFromDevice.XOR) {
                                                                                                                                                            return [
                                                                                                                                                                {
                                                                                                                                                                    title: '异或Token标志',
                                                                                                                                                                    right: {
                                                                                                                                                                        type: 'text',
                                                                                                                                                                        value: deviceConfig.DMAFromDevice.XORHex
                                                                                                                                                                    },
                                                                                                                                                                    async callBack() {
                                                                                                                                                                        let input = tool.controls.input.singleText({
                                                                                                                                                                            title: '异或Token标志',
                                                                                                                                                                            value: deviceConfig.DMAFromDevice.XORHex,
                                                                                                                                                                            async okCallBack(e) {
                                                                                                                                                                                deviceConfig.DMAFromDevice.XORHex = e
                                                                                                                                                                                refreshPage_editDeviceConfig()
                                                                                                                                                                                input.close()
                                                                                                                                                                                setEdited()
                                                                                                                                                                            },
                                                                                                                                                                            checkCallBack(e = '') {
                                                                                                                                                                                if (e.match(/[0-9a-zA-Z]{4}/g) === null) throw '应为4位十六进制数'
                                                                                                                                                                            }
                                                                                                                                                                        })
                                                                                                                                                                    }
                                                                                                                                                                },
                                                                                                                                                            ]
                                                                                                                                                        } else {
                                                                                                                                                            return []
                                                                                                                                                        }
                                                                                                                                                    })()
                                                                                                                                                ]
                                                                                                                                            } else {
                                                                                                                                                return []
                                                                                                                                            }
                                                                                                                                        })()
                                                                                                                                    ]
                                                                                                                                },
                                                                                                                                {
                                                                                                                                    title: '通道',
                                                                                                                                    list: (() => {
                                                                                                                                        let deviceInfo = deviceConfig
                                                                                                                                        let deviceName = deviceConfig.name
                                                                                                                                        const handleSaveDeviceConfig = async (newConfig) => {
                                                                                                                                            newConfig = JSON.parse(JSON.stringify(newConfig))
                                                                                                                                            delete newConfig.sessions
                                                                                                                                            delete newConfig.channelNum
                                                                                                                                            await tool.flow(async () => {
                                                                                                                                                let re = await tool.requestData('/app/config/deviceInfo_edit', {
                                                                                                                                                    hostName,
                                                                                                                                                    deviceName,
                                                                                                                                                    deviceInfo: newConfig
                                                                                                                                                })
                                                                                                                                                if (re.status) {
                                                                                                                                                    tool.controls.closeTop()
                                                                                                                                                    tool.controls.toast.show({
                                                                                                                                                        content: '修改成功，重启HOST后生效',
                                                                                                                                                        icon: 'info',
                                                                                                                                                        time: 1500
                                                                                                                                                    })
                                                                                                                                                } else {
                                                                                                                                                    throw re.content
                                                                                                                                                }
                                                                                                                                            }, err => {
                                                                                                                                                tool.controls.toast.show({
                                                                                                                                                    content: `${err}`,
                                                                                                                                                    icon: "error",
                                                                                                                                                    time: 1500
                                                                                                                                                })
                                                                                                                                            })
                                                                                                                                        }
                                                                                                                                        const tidyUpChannelData = (config) => {
                                                                                                                                            let toChannels = JSON.parse(JSON.stringify(config.DMAToDevice.channels))
                                                                                                                                            let toChannels_left = 0
                                                                                                                                            for (let i = 0; i < toChannels.length; i++) {
                                                                                                                                                toChannels[i].startTokenIndex = toChannels_left
                                                                                                                                                toChannels_left += toChannels[i].size
                                                                                                                                                toChannels[i].endTokenIndex = toChannels_left - 1
                                                                                                                                            }

                                                                                                                                            let fromChannels = JSON.parse(JSON.stringify(config.DMAFromDevice.channels))
                                                                                                                                            let fromChannels_left = 0
                                                                                                                                            for (let i = 0; i < fromChannels.length; i++) {
                                                                                                                                                fromChannels[i].startTokenIndex = fromChannels_left
                                                                                                                                                fromChannels_left += fromChannels[i].size
                                                                                                                                                fromChannels[i].endTokenIndex = fromChannels_left - 1
                                                                                                                                            }

                                                                                                                                            for (let i = 0; i < fromChannels.length; i++) {
                                                                                                                                                if (fromChannels[i].index === -1) continue
                                                                                                                                                fromChannels[i].toChannelData = toChannels[fromChannels[i].index]
                                                                                                                                            }
                                                                                                                                            fromChannels = fromChannels.filter(item => item.index !== -1)
                                                                                                                                            return fromChannels
                                                                                                                                        }
                                                                                                                                        const changeChannelsToDeviceConfig = (channels, deviceInfo) => {
                                                                                                                                            channels = channels.sort((a, b) => {
                                                                                                                                                return a.toChannelData.startTokenIndex - b.toChannelData.startTokenIndex
                                                                                                                                            })
                                                                                                                                            let toDeviceChannels = []
                                                                                                                                            let fromDeviceChannels = []
                                                                                                                                            for (let i = 0; i < channels.length; i++) {
                                                                                                                                                toDeviceChannels.push({
                                                                                                                                                    size: channels[i].toChannelData.endTokenIndex - channels[i].toChannelData.startTokenIndex + 1,
                                                                                                                                                    startTokenIndex: channels[i].toChannelData.startTokenIndex,
                                                                                                                                                    endTokenIndex: channels[i].toChannelData.endTokenIndex,
                                                                                                                                                    availble: true
                                                                                                                                                })
                                                                                                                                                fromDeviceChannels.push({
                                                                                                                                                    size: channels[i].endTokenIndex - channels[i].startTokenIndex + 1,
                                                                                                                                                    startTokenIndex: channels[i].startTokenIndex,
                                                                                                                                                    endTokenIndex: channels[i].endTokenIndex
                                                                                                                                                })
                                                                                                                                            }
                                                                                                                                            for (let i = toDeviceChannels.length - 2; i >= 0; i--) {
                                                                                                                                                let currentItem = toDeviceChannels[i]
                                                                                                                                                let rightItem = toDeviceChannels[i + 1]
                                                                                                                                                if (currentItem.endTokenIndex + 1 !== rightItem.startTokenIndex) {
                                                                                                                                                    toDeviceChannels = [...toDeviceChannels.slice(0, i + 1), {
                                                                                                                                                        size: rightItem.startTokenIndex - currentItem.endTokenIndex - 1,
                                                                                                                                                        startTokenIndex: currentItem.endTokenIndex + 1,
                                                                                                                                                        endTokenIndex: rightItem.startTokenIndex - 1,
                                                                                                                                                        availble: false
                                                                                                                                                    }, ...toDeviceChannels.slice(i + 1)]
                                                                                                                                                    fromDeviceChannels = [...fromDeviceChannels.slice(0, i + 1), undefined, ...fromDeviceChannels.slice(i + 1)]
                                                                                                                                                }
                                                                                                                                            }
                                                                                                                                            for (let i = 0; i < fromDeviceChannels.length; i++) {
                                                                                                                                                if (fromDeviceChannels[i] === undefined) continue
                                                                                                                                                fromDeviceChannels[i].index = i
                                                                                                                                            }
                                                                                                                                            fromDeviceChannels = fromDeviceChannels.filter(item => item !== undefined).sort((a, b) => {
                                                                                                                                                return a.startTokenIndex - b.startTokenIndex
                                                                                                                                            })
                                                                                                                                            for (let i = fromDeviceChannels.length - 2; i >= 0; i--) {
                                                                                                                                                let currentItem = fromDeviceChannels[i]
                                                                                                                                                let rightItem = fromDeviceChannels[i + 1]
                                                                                                                                                if (currentItem.endTokenIndex + 1 !== rightItem.startTokenIndex) {
                                                                                                                                                    fromDeviceChannels = [...fromDeviceChannels.slice(0, i + 1), {
                                                                                                                                                        size: rightItem.startTokenIndex - currentItem.endTokenIndex - 1,
                                                                                                                                                        startTokenIndex: currentItem.endTokenIndex + 1,
                                                                                                                                                        endTokenIndex: rightItem.startTokenIndex - 1,
                                                                                                                                                        index: -1
                                                                                                                                                    }, ...fromDeviceChannels.slice(i + 1)]
                                                                                                                                                }
                                                                                                                                            }
                                                                                                                                            if (fromDeviceChannels.length && fromDeviceChannels[0].startTokenIndex > 0) {
                                                                                                                                                fromDeviceChannels = [{
                                                                                                                                                    size: fromDeviceChannels[0].startTokenIndex,
                                                                                                                                                    startTokenIndex: 0,
                                                                                                                                                    endTokenIndex: fromDeviceChannels[0].startTokenIndex - 1,
                                                                                                                                                    index: -1
                                                                                                                                                }, ...fromDeviceChannels]
                                                                                                                                            }
                                                                                                                                            if (toDeviceChannels.length && toDeviceChannels[0].startTokenIndex > 0) {
                                                                                                                                                toDeviceChannels = [{
                                                                                                                                                    size: toDeviceChannels[0].startTokenIndex,
                                                                                                                                                    startTokenIndex: 0,
                                                                                                                                                    endTokenIndex: toDeviceChannels[0].startTokenIndex - 1,
                                                                                                                                                    availble: false
                                                                                                                                                }, ...toDeviceChannels]
                                                                                                                                                fromDeviceChannels.forEach(item => {
                                                                                                                                                    if (item.index >= 0) item.index++
                                                                                                                                                })
                                                                                                                                            }
                                                                                                                                            fromDeviceChannels = JSON.parse(JSON.stringify(fromDeviceChannels))
                                                                                                                                            fromDeviceChannels.forEach(item => {
                                                                                                                                                delete item.startTokenIndex
                                                                                                                                                delete item.endTokenIndex
                                                                                                                                            });
                                                                                                                                            toDeviceChannels = JSON.parse(JSON.stringify(toDeviceChannels))
                                                                                                                                            toDeviceChannels.forEach(item => {
                                                                                                                                                delete item.startTokenIndex
                                                                                                                                                delete item.endTokenIndex
                                                                                                                                            });
                                                                                                                                            console.log({
                                                                                                                                                fromDeviceChannels,
                                                                                                                                                toDeviceChannels
                                                                                                                                            })
                                                                                                                                            deviceInfo.DMAToDevice.channels = toDeviceChannels
                                                                                                                                            deviceInfo.DMAFromDevice.channels = fromDeviceChannels
                                                                                                                                            return deviceInfo
                                                                                                                                        }
                                                                                                                                        const isRangeRepeat = (channels, type, startTokenIndex, endTokenIndex, screenIndex) => {
                                                                                                                                            if (type === 'to') {
                                                                                                                                                for (let i = 0; i < channels.length; i++) {
                                                                                                                                                    if (i === screenIndex) continue
                                                                                                                                                    let startIndex = channels[i].toChannelData.startTokenIndex
                                                                                                                                                    let endIndex = channels[i].toChannelData.endTokenIndex
                                                                                                                                                    try {
                                                                                                                                                        tool.isRangeRepeat(startIndex, endIndex, startTokenIndex, endTokenIndex)
                                                                                                                                                    } catch (error) {
                                                                                                                                                        return true
                                                                                                                                                    }
                                                                                                                                                }
                                                                                                                                                return false
                                                                                                                                            } else {
                                                                                                                                                for (let i = 0; i < channels.length; i++) {
                                                                                                                                                    if (i === screenIndex) continue
                                                                                                                                                    let startIndex = channels[i].startTokenIndex
                                                                                                                                                    let endIndex = channels[i].endTokenIndex
                                                                                                                                                    try {
                                                                                                                                                        tool.isRangeRepeat(startIndex, endIndex, startTokenIndex, endTokenIndex)
                                                                                                                                                    } catch (error) {
                                                                                                                                                        return true
                                                                                                                                                    }
                                                                                                                                                }
                                                                                                                                                return false
                                                                                                                                            }
                                                                                                                                        }
                                                                                                                                        let re = []
                                                                                                                                        let channels = tidyUpChannelData(deviceInfo)
                                                                                                                                        for (let i = 0; i < channels.length; i++) {
                                                                                                                                            let item = channels[i]
                                                                                                                                            re.push({
                                                                                                                                                title: `输入：${item.toChannelData.startTokenIndex}～${item.toChannelData.endTokenIndex} 输出：${item.startTokenIndex}~${item.endTokenIndex}`,
                                                                                                                                                async callBack() {
                                                                                                                                                    try {
                                                                                                                                                        await new Promise((resolve, reject) => {
                                                                                                                                                            let as = tool.controls.actionSheet({
                                                                                                                                                                tip: `通道 输入：${item.toChannelData.startTokenIndex}～${item.toChannelData.endTokenIndex} 输出：${item.startTokenIndex}~${item.endTokenIndex}`,
                                                                                                                                                                list: [
                                                                                                                                                                    {

                                                                                                                                                                        name: '编辑',
                                                                                                                                                                        callBack: () => {
                                                                                                                                                                            resolve()
                                                                                                                                                                            as.close()
                                                                                                                                                                        }
                                                                                                                                                                    },
                                                                                                                                                                    {
                                                                                                                                                                        name: '删除',
                                                                                                                                                                        callBack() {
                                                                                                                                                                            channels = [...channels.slice(0, i), ...channels.slice(i + 1)]
                                                                                                                                                                            changeChannelsToDeviceConfig(channels, deviceInfo)
                                                                                                                                                                            refreshPage_editDeviceConfig()
                                                                                                                                                                            as.close()
                                                                                                                                                                            reject()
                                                                                                                                                                            setEdited()
                                                                                                                                                                        }
                                                                                                                                                                    }
                                                                                                                                                                ]
                                                                                                                                                            })
                                                                                                                                                        })
                                                                                                                                                    } catch (error) {
                                                                                                                                                        return
                                                                                                                                                    }
                                                                                                                                                    tool.settings.show('编辑通道', (refreshPage_editChannel) => {

                                                                                                                                                        return () => {
                                                                                                                                                            channels = tidyUpChannelData(deviceInfo)
                                                                                                                                                            return [
                                                                                                                                                                {
                                                                                                                                                                    title: 'DMA To Device',
                                                                                                                                                                    list: [
                                                                                                                                                                        {
                                                                                                                                                                            title: '起始Token下标',
                                                                                                                                                                            right: {
                                                                                                                                                                                type: 'text',
                                                                                                                                                                                value: channels[i].toChannelData.startTokenIndex
                                                                                                                                                                            },
                                                                                                                                                                            callBack() {
                                                                                                                                                                                let input = tool.controls.input.singleText({
                                                                                                                                                                                    title: '起始Token下标',
                                                                                                                                                                                    value: channels[i].toChannelData.startTokenIndex,
                                                                                                                                                                                    checkCallBack(e) {
                                                                                                                                                                                        e = parseInt(e)
                                                                                                                                                                                        if (isNaN(e) || e < 0 || e >= deviceInfo.DMAToDevice.tokenNum) throw '应为自然数且不能超过token数量'
                                                                                                                                                                                        if (isRangeRepeat(channels, 'to', e, channels[i].toChannelData.endTokenIndex, i)) throw '和其他通道有冲突'
                                                                                                                                                                                    },
                                                                                                                                                                                    async okCallBack(e) {
                                                                                                                                                                                        e = parseInt(e)
                                                                                                                                                                                        channels[i].toChannelData.startTokenIndex = e
                                                                                                                                                                                        changeChannelsToDeviceConfig(channels, deviceInfo)
                                                                                                                                                                                        input.close()
                                                                                                                                                                                        refreshPage_editChannel()
                                                                                                                                                                                        refreshPage_editDeviceConfig()
                                                                                                                                                                                        setEdited()
                                                                                                                                                                                    }
                                                                                                                                                                                })
                                                                                                                                                                            }
                                                                                                                                                                        },
                                                                                                                                                                        {
                                                                                                                                                                            title: '终止Token下标',
                                                                                                                                                                            right: {
                                                                                                                                                                                type: 'text',
                                                                                                                                                                                value: channels[i].toChannelData.endTokenIndex,
                                                                                                                                                                            },
                                                                                                                                                                            callBack() {
                                                                                                                                                                                let input = tool.controls.input.singleText({
                                                                                                                                                                                    title: '终止Token下标',
                                                                                                                                                                                    value: channels[i].toChannelData.endTokenIndex,
                                                                                                                                                                                    checkCallBack(e) {
                                                                                                                                                                                        e = parseInt(e)
                                                                                                                                                                                        if (isNaN(e) || e < 0 || e >= deviceInfo.DMAToDevice.tokenNum) throw '应为自然数且不能超过token数量'
                                                                                                                                                                                        if (isRangeRepeat(channels, 'to', channels[i].toChannelData.startTokenIndex, e, i)) throw '和其他通道有冲突'
                                                                                                                                                                                    },
                                                                                                                                                                                    async okCallBack(e) {
                                                                                                                                                                                        e = parseInt(e)
                                                                                                                                                                                        channels[i].toChannelData.endTokenIndex = e
                                                                                                                                                                                        changeChannelsToDeviceConfig(channels, deviceInfo)
                                                                                                                                                                                        input.close()
                                                                                                                                                                                        refreshPage_editChannel()
                                                                                                                                                                                        refreshPage_editDeviceConfig()
                                                                                                                                                                                        setEdited()
                                                                                                                                                                                    }
                                                                                                                                                                                })
                                                                                                                                                                            }
                                                                                                                                                                        }
                                                                                                                                                                    ]
                                                                                                                                                                },
                                                                                                                                                                {
                                                                                                                                                                    title: 'DMA From Device',
                                                                                                                                                                    list: [
                                                                                                                                                                        {
                                                                                                                                                                            title: '起始Token下标',
                                                                                                                                                                            right: {
                                                                                                                                                                                type: 'text',
                                                                                                                                                                                value: channels[i].startTokenIndex
                                                                                                                                                                            },
                                                                                                                                                                            callBack() {
                                                                                                                                                                                let input = tool.controls.input.singleText({
                                                                                                                                                                                    title: '起始Token下标',
                                                                                                                                                                                    value: channels[i].startTokenIndex,
                                                                                                                                                                                    checkCallBack(e) {
                                                                                                                                                                                        e = parseInt(e)
                                                                                                                                                                                        if (isNaN(e) || e < 0 || e >= deviceInfo.DMAFromDevice.tokenNum) throw '应为自然数且不能超过token数量'
                                                                                                                                                                                        if (isRangeRepeat(channels, 'to', e, channels[i].endTokenIndex, i)) throw '和其他通道有冲突'
                                                                                                                                                                                    },
                                                                                                                                                                                    async okCallBack(e) {
                                                                                                                                                                                        e = parseInt(e)
                                                                                                                                                                                        channels[i].startTokenIndex = e
                                                                                                                                                                                        changeChannelsToDeviceConfig(channels, deviceInfo)
                                                                                                                                                                                        input.close()
                                                                                                                                                                                        refreshPage_editChannel()
                                                                                                                                                                                        refreshPage_editDeviceConfig()
                                                                                                                                                                                        setEdited()
                                                                                                                                                                                    }
                                                                                                                                                                                })
                                                                                                                                                                            }
                                                                                                                                                                        },
                                                                                                                                                                        {
                                                                                                                                                                            title: '终止Token下标',
                                                                                                                                                                            right: {
                                                                                                                                                                                type: 'text',
                                                                                                                                                                                value: channels[i].endTokenIndex
                                                                                                                                                                            },
                                                                                                                                                                            callBack() {
                                                                                                                                                                                let input = tool.controls.input.singleText({
                                                                                                                                                                                    title: '终止Token下标',
                                                                                                                                                                                    value: channels[i].endTokenIndex,
                                                                                                                                                                                    checkCallBack(e) {
                                                                                                                                                                                        e = parseInt(e)
                                                                                                                                                                                        if (isNaN(e) || e < 0 || e >= deviceInfo.DMAFromDevice.tokenNum) throw '应为自然数且不能超过token数量'
                                                                                                                                                                                        if (isRangeRepeat(channels, 'to', channels[i].startTokenIndex, e, i)) throw '和其他通道有冲突'
                                                                                                                                                                                    },
                                                                                                                                                                                    async okCallBack(e) {
                                                                                                                                                                                        e = parseInt(e)
                                                                                                                                                                                        channels[i].endTokenIndex = e
                                                                                                                                                                                        changeChannelsToDeviceConfig(channels, deviceInfo)
                                                                                                                                                                                        input.close()
                                                                                                                                                                                        refreshPage_editChannel()
                                                                                                                                                                                        refreshPage_editDeviceConfig()
                                                                                                                                                                                        setEdited()
                                                                                                                                                                                    }
                                                                                                                                                                                })
                                                                                                                                                                            }
                                                                                                                                                                        }
                                                                                                                                                                    ]
                                                                                                                                                                }
                                                                                                                                                            ]
                                                                                                                                                        }
                                                                                                                                                    })
                                                                                                                                                }
                                                                                                                                            })
                                                                                                                                        }
                                                                                                                                        re.push({
                                                                                                                                            title: `添加`,
                                                                                                                                            callBack() {
                                                                                                                                                tool.settings.show('新建通道', (refreshPage_addChannel) => {
                                                                                                                                                    const item = {
                                                                                                                                                        startTokenIndex: 0,
                                                                                                                                                        endTokenIndex: 0,
                                                                                                                                                        toChannelData: {
                                                                                                                                                            startTokenIndex: 0,
                                                                                                                                                            endTokenIndex: 0
                                                                                                                                                        }
                                                                                                                                                    }
                                                                                                                                                    return () => {
                                                                                                                                                        return [
                                                                                                                                                            {
                                                                                                                                                                title: 'DMA To Device',
                                                                                                                                                                list: [
                                                                                                                                                                    {
                                                                                                                                                                        title: '起始下标',
                                                                                                                                                                        right: {
                                                                                                                                                                            type: 'text',
                                                                                                                                                                            value: item.toChannelData.startTokenIndex
                                                                                                                                                                        },
                                                                                                                                                                        callBack() {
                                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                                title: `toDevice起始下标`,
                                                                                                                                                                                value: item.toChannelData.startTokenIndex,
                                                                                                                                                                                checkCallBack(e) {
                                                                                                                                                                                    e = parseInt(e)
                                                                                                                                                                                    if (isNaN(e) || e < 0 || e >= deviceInfo.DMAToDevice.tokenNum) throw '应为自然数且不能超过token数量'
                                                                                                                                                                                },
                                                                                                                                                                                okCallBack(e) {
                                                                                                                                                                                    item.toChannelData.startTokenIndex = parseInt(e)
                                                                                                                                                                                    input.close()
                                                                                                                                                                                    refreshPage_addChannel()
                                                                                                                                                                                }
                                                                                                                                                                            })
                                                                                                                                                                        }
                                                                                                                                                                    },
                                                                                                                                                                    {
                                                                                                                                                                        title: '终止下标',
                                                                                                                                                                        right: {
                                                                                                                                                                            type: 'text',
                                                                                                                                                                            value: item.toChannelData.endTokenIndex
                                                                                                                                                                        },
                                                                                                                                                                        callBack() {
                                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                                title: `toDevice终止下标`,
                                                                                                                                                                                value: item.toChannelData.endTokenIndex,
                                                                                                                                                                                checkCallBack(e) {
                                                                                                                                                                                    e = parseInt(e)
                                                                                                                                                                                    if (isNaN(e) || e < 0 || e >= deviceInfo.DMAToDevice.tokenNum) throw '应为自然数且不能超过token数量'
                                                                                                                                                                                },
                                                                                                                                                                                okCallBack(e) {
                                                                                                                                                                                    item.toChannelData.endTokenIndex = parseInt(e)
                                                                                                                                                                                    input.close()
                                                                                                                                                                                    refreshPage_addChannel()
                                                                                                                                                                                }
                                                                                                                                                                            })
                                                                                                                                                                        }
                                                                                                                                                                    }
                                                                                                                                                                ]
                                                                                                                                                            },
                                                                                                                                                            {
                                                                                                                                                                title: 'DMA From Device',
                                                                                                                                                                list: [
                                                                                                                                                                    {
                                                                                                                                                                        title: '起始下标',
                                                                                                                                                                        right: {
                                                                                                                                                                            type: 'text',
                                                                                                                                                                            value: item.startTokenIndex
                                                                                                                                                                        },
                                                                                                                                                                        callBack() {
                                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                                title: `fromDevice起始下标`,
                                                                                                                                                                                value: item.startTokenIndex,
                                                                                                                                                                                checkCallBack(e) {
                                                                                                                                                                                    e = parseInt(e)
                                                                                                                                                                                    if (isNaN(e) || e < 0 || e >= deviceInfo.DMAFromDevice.tokenNum) throw '应为自然数且不能超过token数量'
                                                                                                                                                                                },
                                                                                                                                                                                okCallBack(e) {
                                                                                                                                                                                    item.startTokenIndex = parseInt(e)
                                                                                                                                                                                    input.close()
                                                                                                                                                                                    refreshPage_addChannel()
                                                                                                                                                                                }
                                                                                                                                                                            })
                                                                                                                                                                        }
                                                                                                                                                                    },
                                                                                                                                                                    {
                                                                                                                                                                        title: '终止下标',
                                                                                                                                                                        right: {
                                                                                                                                                                            type: "text",
                                                                                                                                                                            value: item.endTokenIndex
                                                                                                                                                                        },
                                                                                                                                                                        callBack() {
                                                                                                                                                                            let input = tool.controls.input.singleText({
                                                                                                                                                                                title: `fromDevice起始下标`,
                                                                                                                                                                                value: item.endTokenIndex,
                                                                                                                                                                                checkCallBack(e) {
                                                                                                                                                                                    e = parseInt(e)
                                                                                                                                                                                    if (isNaN(e) || e < 0 || e >= deviceInfo.DMAFromDevice.tokenNum) throw '应为自然数且不能超过token数量'
                                                                                                                                                                                },
                                                                                                                                                                                okCallBack(e) {
                                                                                                                                                                                    item.endTokenIndex = parseInt(e)
                                                                                                                                                                                    input.close()
                                                                                                                                                                                    refreshPage_addChannel()
                                                                                                                                                                                }
                                                                                                                                                                            })
                                                                                                                                                                        }
                                                                                                                                                                    }
                                                                                                                                                                ]
                                                                                                                                                            },
                                                                                                                                                            {
                                                                                                                                                                title: '操作',
                                                                                                                                                                list: [
                                                                                                                                                                    {
                                                                                                                                                                        title: '保存',
                                                                                                                                                                        callBack() {
                                                                                                                                                                            tool.flow(async () => {
                                                                                                                                                                                if (isRangeRepeat(channels, 'to', item.toChannelData.startTokenIndex, item.toChannelData.endTokenIndex)) throw '和现有通道有冲突'
                                                                                                                                                                                if (isRangeRepeat(channels, 'from', item.startTokenIndex, item.endTokenIndex)) throw '和现有通道有冲突'
                                                                                                                                                                                channels.push(item)
                                                                                                                                                                                changeChannelsToDeviceConfig(channels, deviceInfo)
                                                                                                                                                                                tool.controls.toast.show({
                                                                                                                                                                                    content: `已添加`,
                                                                                                                                                                                    icon: 'success',
                                                                                                                                                                                    time: 2000
                                                                                                                                                                                })
                                                                                                                                                                                tool.settings.close.top()
                                                                                                                                                                                refreshPage_editDeviceConfig()
                                                                                                                                                                                setEdited()
                                                                                                                                                                            }, err => {
                                                                                                                                                                                tool.controls.toast.show({
                                                                                                                                                                                    content: `${err}`,
                                                                                                                                                                                    icon: 'error',
                                                                                                                                                                                    time: 2000
                                                                                                                                                                                })
                                                                                                                                                                            })
                                                                                                                                                                        }
                                                                                                                                                                    },
                                                                                                                                                                ]
                                                                                                                                                            }
                                                                                                                                                        ]
                                                                                                                                                    }
                                                                                                                                                })
                                                                                                                                            }
                                                                                                                                        })
                                                                                                                                        return re
                                                                                                                                    })()
                                                                                                                                }
                                                                                                                            ]
                                                                                                                        }
                                                                                                                    })
                                                                                                                }
                                                                                                            })
                                                                                                        }
                                                                                                        return re
                                                                                                    })()
                                                                                                },
                                                                                                {
                                                                                                    title: 'ollama',
                                                                                                    list: (() => {
                                                                                                        let re = []
                                                                                                        hostConfig.ollamaInstalledModels.forEach(item => {
                                                                                                            re.push({
                                                                                                                title: item,
                                                                                                                callBack() {
                                                                                                                    let as = tool.controls.actionSheet({
                                                                                                                        list: [
                                                                                                                            {
                                                                                                                                name: '删除此模型',
                                                                                                                                callBack() {
                                                                                                                                    try {
                                                                                                                                        for (let i = 0; i < hostConfig.devices.length; i++) {
                                                                                                                                            if (hostConfig.devices[i].ollama.model === item && hostConfig.devices[i].type === 'ollama') {
                                                                                                                                                throw '有设备使用此模型，无法删除'
                                                                                                                                            }
                                                                                                                                        }
                                                                                                                                        hostConfig.ollamaInstalledModels = hostConfig.ollamaInstalledModels.filter(e => e != item)
                                                                                                                                        refreshPage_editConfig()
                                                                                                                                        as.close()
                                                                                                                                        setEdited()
                                                                                                                                    } catch (error) {
                                                                                                                                        as.close()
                                                                                                                                        tool.controls.modal({
                                                                                                                                            title: `${error}`,
                                                                                                                                            showCancel: false
                                                                                                                                        })
                                                                                                                                    }
                                                                                                                                }
                                                                                                                            }
                                                                                                                        ]
                                                                                                                    })
                                                                                                                }
                                                                                                            })
                                                                                                        })
                                                                                                        re.push({
                                                                                                            title: '添加已安装的模型',
                                                                                                            callBack() {
                                                                                                                let input = tool.controls.input.singleText({
                                                                                                                    title: '输入模型名称',
                                                                                                                    okCallBack(e) {
                                                                                                                        hostConfig.ollamaInstalledModels.push(e)
                                                                                                                        input.close()
                                                                                                                        setEdited()
                                                                                                                        refreshPage_editConfig()
                                                                                                                    },
                                                                                                                    checkCallBack(e) {
                                                                                                                        if (!e) throw '输入模型名称'
                                                                                                                        if ((hostConfig.ollamaInstalledModels.indexOf(e) + 1)) throw '模型已存在'
                                                                                                                    }
                                                                                                                })
                                                                                                            }
                                                                                                        })
                                                                                                        return re
                                                                                                    })()
                                                                                                }
                                                                                            ]
                                                                                        }
                                                                                    }, async (refreshPage_editConfig) => {
                                                                                        const handleSaveConfig = async (newConfig) => {
                                                                                            newConfig = JSON.parse(JSON.stringify(newConfig))
                                                                                            await tool.flow(async () => {
                                                                                                let re = await tool.requestData('/app/config/hostInfo_save', {
                                                                                                    hostName,
                                                                                                    data: newConfig
                                                                                                })
                                                                                                if (re.status) {
                                                                                                    edited.value = false
                                                                                                    let md = tool.controls.modal({
                                                                                                        content: '配置保存成功，重启当前Host后端程序后生效，是否立刻重启？',
                                                                                                        title: '提示',
                                                                                                        showCancel: true,
                                                                                                        okText: '立刻重启',
                                                                                                        cancelText: '稍后',
                                                                                                        cancelCallBack: () => md.close(),
                                                                                                        okCallBack: async () => {
                                                                                                            let re = await tool.requestData('/app/config/hostInfo_edit', {
                                                                                                                hostName,
                                                                                                                op: 'restart',
                                                                                                                data: {}
                                                                                                            })
                                                                                                            if (re.status) {
                                                                                                                tool.settings.close.top()
                                                                                                                tool.settings.close.top()
                                                                                                                tool.controls.closeTop()
                                                                                                                tool.controls.toast.show({
                                                                                                                    content: '重启指令已发送',
                                                                                                                    icon: 'info',
                                                                                                                    time: 1500
                                                                                                                })
                                                                                                                setTimeout(async () => {
                                                                                                                    try {
                                                                                                                        hostList = await getHostList()
                                                                                                                        refreshPage_onlineHosts()
                                                                                                                    } catch (error) {

                                                                                                                    }
                                                                                                                }, 1000);
                                                                                                                setTimeout(async () => {
                                                                                                                    try {
                                                                                                                        hostList = await getHostList()
                                                                                                                        refreshPage_onlineHosts()
                                                                                                                    } catch (error) {

                                                                                                                    }
                                                                                                                }, 4000);
                                                                                                            } else {
                                                                                                                tool.controls.toast.show({
                                                                                                                    content: `${re.content}`,
                                                                                                                    icon: 'error',
                                                                                                                    time: 1500
                                                                                                                })
                                                                                                            }
                                                                                                        }
                                                                                                    })
                                                                                                } else {
                                                                                                    throw re.content
                                                                                                }
                                                                                            }, err => {
                                                                                                tool.controls.toast.show({
                                                                                                    content: `${err}`,
                                                                                                    icon: "error",
                                                                                                    time: 1500
                                                                                                })
                                                                                            })
                                                                                        }
                                                                                        await handleSaveConfig(hostConfig)
                                                                                    }, '保存')
                                                                                } else {
                                                                                    throw re.content
                                                                                }
                                                                            }, err => {
                                                                                tool.controls.toast.show({
                                                                                    content: `${err}`,
                                                                                    icon: "error",
                                                                                    time: 1500
                                                                                })
                                                                            })
                                                                        }
                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    }
                                                })
                                                return
                                                await tool.flow(async () => {
                                                    let re = await tool.requestData('/app/config/get', {
                                                        hostName
                                                    }, 'get')
                                                    if (re.status) {
                                                        let hostInfo = re.data
                                                        console.log(hostInfo)
                                                        tool.settings.show(`${hostName}`, async () => {
                                                            return () => {

                                                            }
                                                        })
                                                    } else {
                                                        throw re.content
                                                    }
                                                }, err => {
                                                    tool.controls.toast.show({
                                                        content: `${err}`,
                                                        icon: "error",
                                                        time: 1500
                                                    })
                                                })

                                            }
                                            hostList = await getHostList()
                                            return () => {
                                                let re = []
                                                for (let i = 0; i < hostList.length; i++) {
                                                    re.push({
                                                        title: hostList[i].hostName,
                                                        callBack: () => handleShowHostConfigMenu(hostList[i].hostName)
                                                    })
                                                }
                                                if (re.length) {
                                                    return [
                                                        {
                                                            list: re
                                                        }
                                                    ]
                                                } else {
                                                    return [
                                                        {
                                                            title: '无'
                                                        }
                                                    ]
                                                }
                                            }
                                        }, async (refreshPage_onlineHosts) => {
                                            try {
                                                hostList = await getHostList()
                                                refreshPage_onlineHosts()
                                            } catch (error) {

                                            }
                                        }, '刷新')
                                    }, err => {
                                        tool.controls.toast.show({
                                            content: `${err}`,
                                            icon: "error",
                                            time: 1500
                                        })
                                    })
                                }
                            }
                        ]
                    },
                    {
                        title: '聊天',
                        list: [
                            {
                                title: '显示调试信息',
                                right: {
                                    type: 'text',
                                    value: mode.value
                                },
                                callBack() {
                                    let as = tool.controls.actionSheet({
                                        tip: '显示调试信息',
                                        list: [
                                            {
                                                name: 'Demo (不显示)',
                                                callBack: () => {
                                                    mode.value = 'Demo'
                                                    as.close()
                                                    refreshPage_settings()
                                                }
                                            },
                                            {
                                                name: '测试 (显示)',
                                                callBack: () => {
                                                    mode.value = '测试'
                                                    as.close()
                                                    refreshPage_settings()
                                                }
                                            },
                                        ]
                                    })
                                }
                            },
                            {
                                title: '发送TokenIds',
                                right: {
                                    type: 'switch',
                                    value: chatBox.sendTokenIds
                                },
                                callBack(e) {
                                    chatBox.sendTokenIds = e
                                    refreshPage_settings()
                                }
                            },
                            {
                                title: '0秒时发送（用于并发测试）',
                                right: {
                                    type: 'switch',
                                    value: chatBox.sendAtZeroSecond
                                },
                                callBack(e) {
                                    chatBox.sendAtZeroSecond = e
                                    refreshPage_settings()
                                }
                            },
                        ]
                    }
                ]
            }
        })
    }
    show()
}

onMounted(async () => {
    await tool.flow(async () => {
        {
            let re = await welcome.get()
            welcome.session_id = re.session_id
            model.list = re.model_list
            model.currentModelId = re.currentModelId
            chatList.push.ruru(re.message, false)
        }

        show.value = true
        await tool.wait(0.01)
        tool.store.setItem('setWindowData')
    }, error => {
        let md = tool.controls.modal({
            title: '提示',
            content: `${error}`,
            showCancel: true,
            okText: '打开设置',
            okCallBack() {
                md.close()
                adminSettings()
            },
            cancelCallBack() {
                md.close()
            },
            cancelText: '确定'
        })
    })
})

</script>

<style scoped></style>